#pragma once
#include "util.hpp"

namespace qbe::editing::Drift {

void initOffsetFunc(DriftModel& param) {
  param.grpc_interface.initOffSet();
}

std::string offsetFunc(DriftModel& param, std::string& json_str) {
  tools::GrpcResponse res = param.grpc_interface.offsetFunc(json_str);
  return res.data;
}

std::vector<qlib::Vec2d> objectCoordinatePoints(std::vector<double> coordinate) {
  std::vector<qlib::Vec2d> points;
  for (int i = 0; i < coordinate.size(); i = i + 2) {
    points.push_back(qlib::Vec2d(coordinate[i], coordinate[i + 1]));
  }
  return points;
}

rapidjson::Value vector_array_double(std::vector<double> vaules, rapidjson::Document::AllocatorType& allocator) {
  rapidjson::Value a(rapidjson::kArrayType);
  for (auto i : vaules) {
    a.PushBack(i, allocator);
  }
  return a;
}

rapidjson::Value vector_vector_array_double(std::vector<std::vector<double>> vaules, rapidjson::Document::AllocatorType& allocator) {
  rapidjson::Value a(rapidjson::kArrayType);
  //列表中镶嵌列表
  for (auto value : vaules) {
    rapidjson::Value a_1(rapidjson::kArrayType);
    for (auto i : value) {
      a_1.PushBack(i, allocator);
    }
    a.PushBack(a_1, allocator);
  }
  return a;
}

std::vector<std::vector<double>> array_vectot_vector_double(rapidjson::Value& value) {
  std::vector<std::vector<double>> result;
  if (value.IsArray()) {
    for (int i = 0; i < value.Size(); i++) {
      if (value[i].IsArray()) {
        std::vector<double> temp;
        for (int j = 0; j < value[i].Size(); j++) {
          temp.push_back(value[i][j].GetDouble());
        }
        result.push_back(temp);
      }
    }
  }
  return result;
}

//偏移线
void driftLineFunc(DriftModel& param, qlib::Path::s_ptr line_node, double x, double y) {
  // 组装参数 线的点坐标集合、叉积、偏移距离、属性
  if (line_node == nullptr) {
    return;
  }

  double line_width = 0;  //line->m_elements[0].m_half_width_and_offset.x * 2; //判断骨架线
  if (line_width != 0)
    return;
  std::vector<double> coordinate;
  coordinate.push_back(x);
  coordinate.push_back(y);
  std::vector<qlib::Vec2d> point_array = line_node->spine.points;
  std::vector<double> point_arrays;
  for (auto i : point_array) {
    point_arrays.push_back(i.x);
    point_arrays.push_back(i.y);
  }
  // LayoutCtrlData::deleteRenderElement(copy_ele);
  // for (auto i : m_line_eles) {
  //   if (i)
  //     LayoutCtrlData::deleteRenderElement(i);
  // }
  param.m_line_eles.clear();  //清除渲染
  const char* json = "{\"name\":\"offset\"}";
  rapidjson::Document d;
  d.Parse(json);
  // 2. 利用 DOM 作出修改。
  rapidjson::Document::AllocatorType& allocator = d.GetAllocator();
  //加入列表成员
  d.AddMember("points_origin", vector_array_double(point_arrays, allocator), allocator);
  d.AddMember("d", param.m_drift_distance, allocator);
  d.AddMember("mouse_points", vector_array_double(coordinate, allocator), allocator);
  d.AddMember("object", 0, allocator);
  // 3. 把 DOM 转换（stringify）成 JSON。
  rapidjson::StringBuffer buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  d.Accept(writer);
  std::string json_param = buffer.GetString();
  auto result_str = offsetFunc(param, json_param);
  if (result_str == "")
    return;
  rapidjson::Document result_d;
  result_d.Parse(result_str.c_str());
  rapidjson::Value& s = result_d["code"];
  auto v = s.GetInt();
  std::vector<std::vector<double>> points;
  if (v == 0) {
    rapidjson::Value& s = result_d["data"];
    points = array_vectot_vector_double(s);
    for (auto i : points) {
      std::vector<qlib::Vec2d> intersection_points = objectCoordinatePoints(i);
      // 构造偏移后的折线
      // osg::ref_ptr<LineNode> drift_line_geode = new LineNode(&LayoutCtrlData::getLayerStyleInfoOnNum);
      // int current_layer_num = LayoutCtrlData::getCurrentSelectLayerNum();
      // drift_line_geode->ss = LayoutCtrlData::createFillShaderStateSet(current_layer_num);
      // drift_line_geode->ss->setRenderBinDetails(200, "RenderBin");
      // drift_line_geode->m_line_ss = LayoutCtrlData::createLineShaderStateSet(current_layer_num);
      // drift_line_geode->m_line_ss->setRenderBinDetails(200, "RenderBin");
      // drift_line_geode->create(ViewKernel::roundFunc(intersection_points[0].x, 1000),
      //                          ViewKernel::roundFunc(intersection_points[0].y, 1000));
      // for (auto&& i : drift_line_geode->m_flexpath->m_elements) {
      //   i.m_layer = current_layer_num;
      // }
      // drift_line_geode->m_is_pick = false;
      // drift_line_geode->updateLayerStateSet();

      // for (size_t i = 1; i < intersection_points.size(); ++i) {
      //   qlib::Vec2d p = intersection_points[i];
      //   drift_line_geode->addPoint(ViewKernel::roundFunc(p.x, 1000), ViewKernel::roundFunc(p.y, 1000));
      // }
      // m_line_eles.push_back(drift_line_geode);
      // LayoutCtrlData::addRenderElement(drift_line_geode);
      // drift_line_geode->setLineStyle(true, 10, 30, osg::Vec4f(0.50588f, 0.98824f, 0.01569f, 1.0f));
      // drift_line_geode->update();

      qlib::Path::s_ptr path = qlib::Path::create();
      path->spine.points = intersection_points;
      path->layer = param.layer;
      param.m_line_eles.push_back(path);
      param.m_can_create = true;
    }
  } else if (v == -1) {
    param.is_too_large = true;
    // LayoutCtrlData::sendOperaterMessageInfo(tr("mode: drift element | drift distance is too large"));
  }
}

void driftPolygonFunc(DriftModel& param, qlib::Polygon::s_ptr polygon_node, double x, double y) {
  if (polygon_node == nullptr) {
    return;
  }
  std::vector<double> coordinate;
  coordinate.push_back(x);
  coordinate.push_back(y);
  std::vector<qlib::Vec2d> point_array = polygon_node->points;
  std::vector<double> point_arrays;
  for (auto i : point_array) {
    point_arrays.push_back(i.x);
    point_arrays.push_back(i.y);
  }
  // LayoutCtrlData::deleteRenderElement(copy_ele);
  // for (auto i : m_polygon_eles) {
  //   if (i)
  //     LayoutCtrlData::deleteRenderElement(i);
  // }
  param.m_polygon_eles.clear();  //清除渲染
  // for (auto i : m_line_eles) {
  //   if (i)
  //     LayoutCtrlData::deleteRenderElement(i);
  // }
  param.m_line_eles.clear();
  const char* json = "{\"name\":\"offset\"}";
  rapidjson::Document d;
  d.Parse(json);
  // 2. 利用 DOM 作出修改。
  rapidjson::Document::AllocatorType& allocator = d.GetAllocator();
  //加入列表成员
  d.AddMember("points_origin", vector_array_double(point_arrays, allocator), allocator);
  d.AddMember("d", param.m_drift_distance, allocator);
  d.AddMember("mouse_points", vector_array_double(coordinate, allocator), allocator);
  d.AddMember("object", 1, allocator);

  // 3. 把 DOM 转换（stringify）成 JSON。
  rapidjson::StringBuffer buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  d.Accept(writer);
  std::string json_param = buffer.GetString();
  auto result_str = offsetFunc(param, json_param);
  if (result_str == "")
    return;
  rapidjson::Document result_d;
  result_d.Parse(result_str.c_str());
  rapidjson::Value& s = result_d["code"];
  auto v = s.GetInt();
  std::vector<std::vector<double>> points;
  if (v == 0) {
    rapidjson::Value& s = result_d["data"];
    points = array_vectot_vector_double(s);
    for (auto i : points) {
      std::vector<qlib::Vec2d> intersection_points = objectCoordinatePoints(i);
      if (intersection_points[0].x == intersection_points[intersection_points.size() - 1].x &&
          intersection_points[0].y == intersection_points[intersection_points.size() - 1].y) {
        intersection_points.erase(intersection_points.end() - 1);
        // // 构造偏移后的多边形
        // osg::ref_ptr<PolygonNode> drift_polygon_geode = new PolygonNode(&LayoutCtrlData::getLayerStyleInfoOnNum);
        // int current_layer_num = LayoutCtrlData::getCurrentSelectLayerNum();
        // drift_polygon_geode->ss = LayoutCtrlData::createFillShaderStateSet(current_layer_num);
        // drift_polygon_geode->ss->setRenderBinDetails(200, "RenderBin");
        // drift_polygon_geode->m_line_ss = LayoutCtrlData::createLineShaderStateSet(current_layer_num);
        // drift_polygon_geode->m_line_ss->setRenderBinDetails(200, "RenderBin");
        // drift_polygon_geode->create(ViewKernel::roundFunc(intersection_points[0].x, 1000),
        //                             ViewKernel::roundFunc(intersection_points[0].y, 1000));
        // drift_polygon_geode->m_polygon->m_layer = current_layer_num;
        // drift_polygon_geode->m_is_pick = false;
        // drift_polygon_geode->updateLayerStateSet();

        // for (size_t i = 1; i < intersection_points.size(); ++i) {
        //   Vec2 p = intersection_points[i];
        //   drift_polygon_geode->addPoint(ViewKernel::roundFunc(p.x, 1000), ViewKernel::roundFunc(p.y, 1000));
        // }
        // drift_polygon_geode->m_polygon->m_point_array.erase(drift_polygon_geode->m_polygon->m_point_array.begin());
        // m_polygon_eles.push_back(drift_polygon_geode);
        // LayoutCtrlData::addRenderElement(drift_polygon_geode);
        // drift_polygon_geode->setLineStyle(true, 10, 30, osg::Vec4f(0.50588f, 0.98824f, 0.01569f, 1.0f));
        // drift_polygon_geode->update();

        qlib::Polygon::s_ptr polygon = qlib::Polygon::create();
        polygon->points = intersection_points;
        polygon->layer = param.layer;
        param.m_polygon_eles.push_back(polygon);
        param.m_can_create = true;
      } else {
        // osg::ref_ptr<LineNode> drift_line_geode = new LineNode(&LayoutCtrlData::getLayerStyleInfoOnNum);
        // int current_layer_num = LayoutCtrlData::getCurrentSelectLayerNum();
        // drift_line_geode->ss = LayoutCtrlData::createFillShaderStateSet(current_layer_num);
        // drift_line_geode->ss->setRenderBinDetails(200, "RenderBin");
        // drift_line_geode->m_line_ss = LayoutCtrlData::createLineShaderStateSet(current_layer_num);
        // drift_line_geode->m_line_ss->setRenderBinDetails(200, "RenderBin");
        // drift_line_geode->create(ViewKernel::roundFunc(intersection_points[0].x, 1000),
        //                          ViewKernel::roundFunc(intersection_points[0].y, 1000));
        // for (auto&& i : drift_line_geode->m_flexpath->m_elements) {
        //   i.m_layer = current_layer_num;
        // }
        // drift_line_geode->m_is_pick = false;
        // drift_line_geode->updateLayerStateSet();

        // for (size_t i = 1; i < intersection_points.size(); ++i) {
        //   Vec2 p = intersection_points[i];
        //   drift_line_geode->addPoint(ViewKernel::roundFunc(p.x, 1000), ViewKernel::roundFunc(p.y, 1000));
        // }
        // m_line_eles.push_back(drift_line_geode);
        // LayoutCtrlData::addRenderElement(drift_line_geode);
        // drift_line_geode->setLineStyle(true, 10, 30, osg::Vec4f(0.50588f, 0.98824f, 0.01569f, 1.0f));
        // drift_line_geode->update();
        qlib::Path::s_ptr path = qlib::Path::create();
        path->spine.points = intersection_points;
        path->layer = param.layer;
        param.m_line_eles.push_back(path);
        param.m_can_create = true;
      }
    }
  } else if (v == -1) {
    param.is_too_large = true;
    // LayoutCtrlData::sendOperaterMessageInfo(tr("mode: drift element | drift distance is too large"));
  }
}

void driftRectangle(DriftModel& param, qlib::Rectangle::s_ptr rectangle_node, double x, double y) {
  double rectangle_width = std::abs(rectangle_node->width);
  double rectangle_height = std::abs(rectangle_node->height);
  double halfWidth = rectangle_width / 2;
  double halfHeight = rectangle_height / 2;
  qlib::Vec2d rectangle_center;
  rectangle_center.x = rectangle_node->pos.x + halfWidth;
  rectangle_center.y = rectangle_node->pos.y + halfHeight;

  double left_edge_x = rectangle_center.x - halfWidth;
  double right_edge_x = rectangle_center.x + halfWidth;
  double bottom_edge_y = rectangle_center.y - halfHeight;
  double top_edge_y = rectangle_center.y + halfHeight;

  bool in_rectangle = ((x > left_edge_x) && (x < right_edge_x) && (y > bottom_edge_y) && (y < top_edge_y));

  bool onVerticalEdge = (x == left_edge_x || x == right_edge_x) && (y >= bottom_edge_y && y <= top_edge_y);  // 在垂直边上

  bool onHorizontalEdge = (y == bottom_edge_y || y == top_edge_y) && (x >= left_edge_x && x <= right_edge_x);  // 在水平边上

  bool on_rectangle = onVerticalEdge || onHorizontalEdge;

  // RectangleNode* copy_rectangle_node = dynamic_cast<RectangleNode*>(copy_ele.get());
  // copy_rectangle_node->ss->setRenderBinDetails(200, "RenderBin");
  // copy_rectangle_node->m_line_ss->setRenderBinDetails(200, "RenderBin");
  qlib::Rectangle::s_ptr rect = qlib::Rectangle::create();  //渲染对象
  rect->layer = param.layer;
  param.m_rectangle_eles.clear();  //清除渲染
  param.is_too_large = false;
  // 判断点在矩形内部/外部
  double two_distance = param.m_drift_distance * 2;
  if (in_rectangle == true) {  // 矩形向内偏移
    // 偏移距离大于短边长
    if (two_distance >= rectangle_height) {
      // copy_rectangle_node->modify(rectangle_center.x, rectangle_center.y, rectangle_width, rectangle_height);
      rect->pos = rectangle_node->pos;
      rect->width = rectangle_node->width;
      rect->height = rectangle_node->height;
      rect->rotation = rectangle_node->rotation;
      param.m_rectangle_eles.push_back(rect);
      param.m_can_create = false;
      param.is_too_large = true;
      // LayoutCtrlData::sendOperaterMessageInfo(tr("mode: drift element | drift distance is too large"));
      return;
    }
    // copy_rectangle_node->modify(rectangle_center.x, rectangle_center.y, rectangle_width - two_distance,
    //                             rectangle_height - two_distance);
    // copy_rectangle_node->setLineStyle(true, 10, 30, osg::Vec4f(0.50588f, 0.98824f, 0.01569f, 1.0f));
    // copy_rectangle_node->update();
    double w = rectangle_width - two_distance;
    double h = rectangle_height - two_distance;
    rect->pos = qlib::Vec2d(rectangle_center.x - w / 2, rectangle_center.y - h / 2);
    rect->width = w;
    rect->height = h;
    rect->rotation = rectangle_node->rotation;
    param.m_rectangle_eles.push_back(rect);
    param.m_can_create = true;
  }
  if (in_rectangle == false && on_rectangle == false) {
    // 在矩形外部，创建预生成图形
    // copy_rectangle_node->modify(rectangle_center.x, rectangle_center.y, rectangle_width + two_distance,
    //                             rectangle_height + two_distance);
    // copy_rectangle_node->setLineStyle(true, 10, 30, osg::Vec4f(0.50588f, 0.98824f, 0.01569f, 1.0f));
    // copy_rectangle_node->update();
    double w = rectangle_width + two_distance;
    double h = rectangle_height + two_distance;
    rect->pos = qlib::Vec2d(rectangle_center.x - w / 2, rectangle_center.y - h / 2);
    rect->width = w;
    rect->height = h;
    rect->rotation = rectangle_node->rotation;
    rect->layer = param.layer;
    param.m_rectangle_eles.push_back(rect);
    param.m_can_create = true;
  }
}

void driftCircle(DriftModel& param, qlib::Ellipse::s_ptr ellipse_node, double x, double y) {

  // 判断点在圆内部/外部
  qlib::Vec2d center_point = ellipse_node->center;
  double temp_sum = std::pow(center_point.x - x, 2) + std::pow(center_point.y - y, 2);
  double distance_mouse_point = std::sqrt(temp_sum);
  double elli_radius_x = ellipse_node->radius.x;
  double elli_radius_y = ellipse_node->radius.y;

  // EllipseNode* copy_ellipse_node = dynamic_cast<EllipseNode*>(copy_ele.get());
  // copy_ellipse_node->ss->setRenderBinDetails(200, "RenderBin");
  // copy_ellipse_node->m_line_ss->setRenderBinDetails(200, "RenderBin");

  qlib::Ellipse::s_ptr ellipse = qlib::Ellipse::create();  //渲染对象
  ellipse->center = ellipse_node->center;
  ellipse->rotation = ellipse_node->rotation;
  ellipse->tolerance = ellipse_node->tolerance;
  ellipse->layer = param.layer;
  param.m_ellipse_eles.clear();                              //清除渲染
  if (distance_mouse_point < ellipse_node->radius.x) {       // 圆向内偏移
    if (param.m_drift_distance >= ellipse_node->radius.x) {  // 偏移距离大于半径
      // copy_ellipse_node->modify(center_point.x, center_point.y, elli_radius_x, elli_radius_y);
      // copy_ellipse_node->update();
      ellipse->radius = ellipse_node->radius;
      param.m_ellipse_eles.push_back(ellipse);
      param.m_can_create = false;
      param.is_too_large = true;
      // LayoutCtrlData::sendOperaterMessageInfo(tr("mode: drift element | drift distance is too large"));
      return;
    }

    // 在圆内部，创建预生成图形
    // copy_ellipse_node->modify(center_point.x, center_point.y, elli_radius_x - m_drift_distance,
    //                           elli_radius_y - m_drift_distance);
    // copy_ellipse_node->setLineStyle(true, 10, 30, osg::Vec4f(0.50588f, 0.98824f, 0.01569f, 1.0f));
    // copy_ellipse_node->update();

    ellipse->radius = qlib::Vec2d(elli_radius_x - param.m_drift_distance, elli_radius_y - param.m_drift_distance);
    param.m_ellipse_eles.push_back(ellipse);
    param.m_can_create = true;
  }
  if (distance_mouse_point > ellipse_node->radius.x) {  // 圆向外偏移
    // copy_ellipse_node->modify(center_point.x, center_point.y, elli_radius_x + m_drift_distance,
    //                           elli_radius_y + m_drift_distance);
    // copy_ellipse_node->setLineStyle(true, 10, 30, osg::Vec4f(0.50588f, 0.98824f, 0.01569f, 1.0f));
    // copy_ellipse_node->update();

    ellipse->radius = qlib::Vec2d(elli_radius_x + param.m_drift_distance, elli_radius_y + param.m_drift_distance);
    param.m_ellipse_eles.push_back(ellipse);
    param.m_can_create = true;
  }
}

}  // namespace qbe::editing::Drift